#pragma once

#include "Socket.hpp"
#include <iostream>
#include <string>
#include "Socket.hpp"
#include <memory>
#include <jsoncpp/json/json.h>
#include <functional>

using namespace SocketModule;

// 实现一个自定义的网络版本的计算器

// 约定好每个字段的含义，就是协议
// 用户给服务器的请求
class Request
{
public:
    Request()
    {
    }
    Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
    {
    }

    // 序列化
    std::string Serialize()
    {
        // 使用空格做分隔符
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }

        return ok;
    }

    ~Request()
    {
    }

    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }

private:
    int _x;
    int _y;
    char _oper; // 操作码
};

// 服务器给用户的反馈
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code) : _result(result), _code(code)
    {
    }

    ~Response()
    {
    }

    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }

    void SetResult(int res)
    {
        _result = res;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void ShowResult()
    {
        std::cout << "计算结果是：" << _result << "[" << _code << "]" << std::endl;
    }

private:
    int _result; // 为了区分是计算结果还是异常值
    int _code;   // 成功为0，不成功为非0
};

// 协议类
// 保证request和response必须有序列化和反序列化的功能
// 保证读取的时候读到完整的请求序列
// 可以用现成的开源的json库

const std::string sep = "\r\n";

using func_t = std::function<Response(Request &req)>;

class Protocol
{
public:
    Protocol()
    {
    }
    Protocol(func_t func) : _func(func)
    {
    }

    // 给一个json字符串，在前面加上报文长度和有效载荷
    std::string Encode(const std::string jsonstr)
    {
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    bool Decode(std::string &buffer, std::string *package)
    {
        // 判断报文完整性
        // 如果包含至少一个完整请求，提取他并从缓冲区里移除他，方便处理下一个
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
            return false;
        std::string package_len_str = buffer.substr(0, pos);
        int package_len_int = std::stoi(package_len_str); // 报文长度
        int target_len = package_len_str.size() + package_len_int + 2 * sep.size();
        if (buffer.size() < target_len)
            return false; // 不是完整报文

        // 到这里，一定有一个完整报文
        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, target_len); // 提取之后，移除已提取的报文
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string inbuffer; // 缓冲区
        while (true)
        {
            // 读取，从接收缓冲区里读取
            int n = sock->Recv(&inbuffer);
            if (n > 0)
            {
                std::cout << "---------------inbuffer-----------" << std::endl;
                std::cout << inbuffer << std::endl;
                std::cout << "-------------------------------------" << std::endl;
                std::string json_package;
                // 读取成功,解析报文
                bool ret = Decode(inbuffer, &json_package);
                if (!ret)
                {
                    continue;
                }

                std::cout << "---------------inbuffer-----------" << std::endl;
                std::cout << inbuffer << std::endl;
                std::cout << "-------------------------------------" << std::endl;
                // 到这，肯定拿到了完整报文
                // 反序列化
                Request req;
                bool ok = req.Deserialize(json_package);
                if (!ok)
                {
                    continue;
                }
                // 已经得到了一个内部属性已经被设置了的req了
                // 接着可以完成一个计算功能了
                Response resp = _func(req);

                // 序列化
                std::string json_str = resp.Serialize();

                // 添加自定义长度
                std::string send_str = Encode(json_str);

                // 直接发送
                sock->Send(send_str);
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client:" << client.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client: " << client.StringAddr() << ", recv error";
                break;
            }
        }
        sock->Close();
    }

    bool GetResponse(std::shared_ptr<Socket> &client, std::string &resp_buffer, Response *resp)
    {
        // 面向字节流
        while (true)
        {
            int n = client->Recv(&resp_buffer);
            if (n > 0)
            {
                std::cout << "---------------resp_buffer-----------" << std::endl;
                std::cout << resp_buffer << std::endl;
                std::cout << "-------------------------------------" << std::endl;

                // 成功
                std::string json_package;
                // 读取成功,解析报文
                bool ret = Decode(resp_buffer, &json_package);
                if (!ret)
                {
                    continue;
                }

                std::cout << "----------response json---------------" << std::endl;
                std::cout << json_package << std::endl;
                std::cout << "--------------------------------------" << std::endl;

                std::cout << "---------------resp_buffer-----------" << std::endl;
                std::cout << resp_buffer << std::endl;
                std::cout << "-------------------------------------" << std::endl;
                // 肯定拿到了一个完整的应答报文
                // 反序列化
                Response resp;
                resp.Deserialize(json_package);
                return true;
            }
            else if (n == 0)
            {
                std::cout << "server quit" << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
            }
        }
    }

    std::string BuidRequestString(int x, int y, char oper)
    {
        // 构建请求
        Request req(x, y, oper);

        // 序列化
        std::string json_req = req.Serialize();

        std::cout << "------------json_req string-------------" << std::endl;
        std::cout << json_req << std::endl;
        std::cout << "----------------------------------------" << std::endl;

        // 添加长度报头
        return Encode(json_req);
    }

    ~Protocol()
    {
    }

private:
    // Request _req;
    // Response _resp;
    func_t _func;
};